package com.bluedot.www.core.service;

import com.bluedot.www.core.common.HandwritingRuntimeException;
import com.bluedot.www.core.common.OSSConfigure;
import com.bluedot.www.core.common.ResultCodeEnum;
import com.bluedot.www.core.dao.Execute;
import com.bluedot.www.core.pojo.DO.CharacterReport;
import com.bluedot.www.core.pojo.DO.Customer;
import com.bluedot.www.core.pojo.DO.HandwritingImg;
import com.bluedot.www.core.pojo.DTO.AnalyzeBatchResultDTO;
import com.bluedot.www.core.pojo.DTO.ImageListDTO;
import com.bluedot.www.core.utils.DbUtil;
import com.bluedot.www.core.utils.OSSManageUtil;
import com.bluedot.www.framework.mvc.servlet.http.MultipartFile;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.sql.Date;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author jiangnan
 * @version 1.0
 * @date 2021/9/12 16:14
 */
public class HandwritingImgService {

    /**性格报告Mapper*/
    private static final String CHARACTER_REPORT_MAPPER_ADDRESS = "com.bluedot.www.core.mapper.xml.CharacterReportMapper.";
    private static final String HandwritingImg_MAPPER_ADDRESS = "com.bluedot.www.core.mapper.xml.HandwritingImgMapper.";
    private static final String HANDWRITING_IMG_LOCATION = "bluedot/handwritingImg/";
    /**原始图片标志*/
    private static final String ORIGINAL_IMG_MARK = "file0";
    /**预处理后图片标志*/
    private static final String PRETREATED_IMG_MARK = "file1";
    /**OSS 文件需要直接访问的网页前缀*/
    private static final String OSS_ACCESS_URL = OSSConfigure.getInstance().getAccessUrl();

    private static final Logger LOG = LoggerFactory.getLogger(HandwritingImgService.class);


    public static Object execute(String methodName, Object[] param) {

        HandwritingImgService handwritingImgService = new HandwritingImgService();
        Object result = null;
        switch (methodName) {
            case "insertHandwritingImg":
                result = handwritingImgService.insertHandwritingImg((HandwritingImg) param[0]);
                break;
            case "deleteHandwritingImg":
                result = handwritingImgService.deleteHandwritingImg((Long) param[0]);
                break;
            case "listHandwritingImgsByReportId":
                result = handwritingImgService.listHandwritingImgsByReportId((Long) param[0]);
                break;
            case "updateImgFeatureId":
                result = handwritingImgService.updateImgFeatureId((Long) param[0], (Long) param[1]);
                break;
            case "saveHandwritingImg":
                result = handwritingImgService.saveHandwritingImg((List<MultipartFile>) param[0], (Long) param[1],
                        (Integer) param[2], (String) param[3], (Long) param[4]);
                break;
            case "getImageByReportIds":
                result = handwritingImgService.getImageByReportIds((List<Long>) param[0]);
                break;
            case "getImageByReportId":
                result = handwritingImgService.getImageByReportId((Long) param[0]);
                break;
            default:
                throw new RuntimeException("Method NOT FOUND, method name: " + methodName);
        }
        return result;
    }


    /**
     * 插入图片
     *
     * @param handwritingImg
     * @return java.lang.Integer
     * @author jiangnan
     * @date 2021/9/12 16:16
     */
    private boolean insertHandwritingImg(HandwritingImg handwritingImg) {

        Timestamp createTime = DbUtil.getCurrentTime();
        Timestamp modifiedTime = DbUtil.getCurrentTime();
        handwritingImg.setId(DbUtil.generateId());
        handwritingImg.setGmtCreate(createTime);
        handwritingImg.setGmtModified(modifiedTime);
        boolean flag = false;
        Integer i = (Integer) Execute.execute(Execute.UPDATE_TYPE, HandwritingImg_MAPPER_ADDRESS + "insertHandwritingImg", new Object[]{handwritingImg});
        if (i > 0) {
            flag = true;
        }
        return flag;
    }


    /**
     * 根据character_report_id删除
     *
     * @param reportId
     * @return boolean
     * @author jiangnan
     * @date 2021/9/12 16:17
     */
    private boolean deleteHandwritingImg(Long reportId) {
        boolean flag = false;
        Integer i = (Integer) Execute.execute(Execute.UPDATE_TYPE, HandwritingImg_MAPPER_ADDRESS + "deleteHandwritingImg", new Object[]{reportId});
        if (i > 0) {
            flag = true;
        }
        return flag;
    }

    /**
     * @param reportId
     * @return java.util.List<com.bluedot.www.core.pojo.DO.HandwritingImg>
     * @author jiangnan
     * @date 2021/9/12 20:25
     */
    private List<HandwritingImg> listHandwritingImgsByReportId(Long reportId) {
        List<HandwritingImg> list = (List<HandwritingImg>) Execute.execute(Execute.QUERY_TYPE, HandwritingImg_MAPPER_ADDRESS + "listHandwritingImgsByReportId", new Object[]{reportId});
        return list;
    }

    /**
     * 更新笔记图片的特征值编号
     * @param imgId: 笔迹图片编号
     * @param featureId: 特征值编号
     * @return boolean
     * @author He Peng
     * @date 2021/10/20 20:03
     */
    private boolean updateImgFeatureId(Long imgId, Long featureId) {
        Map<String, String> imgIdMap = new HashMap<>(1);
        Map<String, String> featureIdMap = new HashMap<>(1);
        imgIdMap.put("imgId", String.valueOf(imgId));
        featureIdMap.put("featureId", String.valueOf(featureId));
        Integer res = (Integer) Execute.execute(Execute.UPDATE_TYPE,
                HandwritingImg_MAPPER_ADDRESS + "updateImgFeatureId",
                new Object[]{imgIdMap, featureIdMap});
        return res > 0;
    }

    /**
     * 保存原图片笔迹图片和预处理图片
     * @param fileList: 所有图片的文件列表，根据filename
     * @param id: 客户编号或用户编号
     * @param type: 类型，0表示用户，1表示客户
     * @param date: 书写时间
     * @return java.lang.Long 性格报告编号
     * @author He Peng
     * @date 2021/10/26 8:18
     */
    private Long saveHandwritingImg(List<MultipartFile> fileList, Long id, Integer type,
                                    String date, Long preId) {
        List<MultipartFile> originalImgList = new ArrayList<>(6);
        List<MultipartFile> pretreatedImgList = new ArrayList<>(6);
        for (MultipartFile multipartFile : fileList) {
            String filename = multipartFile.getName();
            if (filename.startsWith(PRETREATED_IMG_MARK)) {
                pretreatedImgList.add(multipartFile);
            } else {
                originalImgList.add(multipartFile);
            }
        }
        Long reportId = DbUtil.generateId();
        if (originalImgList.size() != pretreatedImgList.size()) {
            LOG.warn("原图片和预处理图片数量不一致");
            throw new HandwritingRuntimeException(ResultCodeEnum.PARAM_ERROR.getCode(), "参数错误，原图片和预处理图片数量不一致");
        } else {
            if (fileList.size() > 0) {
                CharacterReport characterReport = new CharacterReport();
                characterReport.setId(reportId);
                characterReport.setPreAlgorithmId(preId);
                characterReport.setGmtCreate(DbUtil.getCurrentTime());
                characterReport.setGmtModified(DbUtil.getCurrentTime());
                if (type == 0) {
                    characterReport.setUserId(id);
                    // 如果是普通用户，则使用默认算法 id 设为 -1
                    CharacterReportService.execute("insertReportInUser", new Object[]{characterReport});
                } else {
                    characterReport.setCustomerId(id);
                    CharacterReportService.execute("insertReportInCustomer", new Object[]{characterReport});
                    // 插入性格报告记录后需要更新客户状态为未分析
                    CustomerService.execute("updateCustomerStatus", new Object[]{id, 1});
                }
            }
        }

        // 保存至阿里云OSS，依赖于顺序一致，如果使用采取多线程的方式提高速度，可能导致原图片与预处理后图片无法对应的问题
        List<String> originalPathList = OSSManageUtil.uploadFiles(originalImgList, HANDWRITING_IMG_LOCATION);
        List<String> pretreatedPathList = OSSManageUtil.uploadFiles(pretreatedImgList, HANDWRITING_IMG_LOCATION);

        // 保存至数据库
        int o = originalPathList.size();
        int p = pretreatedPathList.size();
        for (int i = 0; i < o && i < p; i++) {
            HandwritingImg handwritingImg = new HandwritingImg();
            handwritingImg.setId(DbUtil.generateId());
            handwritingImg.setGmtCreate(DbUtil.getCurrentTime());
            handwritingImg.setGmtModified(DbUtil.getCurrentTime());
            handwritingImg.setHandwritingImg(originalPathList.get(i));
            handwritingImg.setPretreatmentImg(pretreatedPathList.get(i));
            handwritingImg.setCharacterReportId(reportId);
            handwritingImg.setWritingTime(Date.valueOf(date.substring(0,10)));
            insertHandwritingImg(handwritingImg);
        }
        return reportId;
    }

    /**
     * 根据性格报告获取笔迹图片
     * @param reportId: 性格报告编号
     * @return java.util.List<com.bluedot.www.core.pojo.DO.HandwritingImg>
     * @author He Peng
     * @date 2021/10/27 13:35
     */
    private List<HandwritingImg> getImageByReportId(Long reportId) {
        List<HandwritingImg> list = (List<HandwritingImg>) Execute.execute(Execute.QUERY_TYPE,
                HandwritingImg_MAPPER_ADDRESS + "getImageByReportId", new Object[]{reportId});
        for (HandwritingImg handwritingImg : list) {
            handwritingImg.setHandwritingImg(OSS_ACCESS_URL + handwritingImg.getHandwritingImg());
            handwritingImg.setPretreatmentImg(OSS_ACCESS_URL + handwritingImg.getPretreatmentImg());
        }
        return list;
    }


    /**
     * 批量分析返回值
     *
     * @param reportIdList 性格报告编号
     * @return java.util.List<com.bluedot.www.core.pojo.DO.HandwritingImg>
     * @author DengHongWei
     * @date 2021/9/7 16:34
     */
    private List<AnalyzeBatchResultDTO> getImageByReportIds(List<Long> reportIdList) {
        List<AnalyzeBatchResultDTO> list = new ArrayList<>();
        for (Long reportId : reportIdList) {
            List<HandwritingImg> images = getImageByReportId(reportId);
            List<ImageListDTO> originalUrlList = new ArrayList<>();
            List<ImageListDTO> pretreatmentUrlList = new ArrayList<>();
            for (HandwritingImg image : images) {
                originalUrlList.add(new ImageListDTO(image.getId(), image.getHandwritingImg()));
                pretreatmentUrlList.add(new ImageListDTO(image.getId(), image.getPretreatmentImg()));
            }
            HandwritingImg handwritingImg = images.get(images.size()-1);
            //不可能不上传图片而生成了性格报告，所以不需要判空处理
            AnalyzeBatchResultDTO handwritingImgDTO = new AnalyzeBatchResultDTO();
            CharacterReport characterReport = (CharacterReport) CharacterReportService.execute(
                    "queryReportDetails", new Object[]{handwritingImg.getCharacterReportId()});
            Customer customer = (Customer) CustomerService.execute("findCustomerById",
                    new Object[]{characterReport.getCustomerId()});
            //设置属性
            handwritingImgDTO.setId(handwritingImg.getCharacterReportId());
            handwritingImgDTO.setName(customer.getName());
            handwritingImgDTO.setTime(handwritingImg.getWritingTime());
            handwritingImgDTO.setSummary(characterReport.getSummary());
            handwritingImgDTO.setOriginalUrlList(originalUrlList);
            handwritingImgDTO.setPretreatmentUrlList(pretreatmentUrlList);
        }
        return list;
    }

}
